<template>
  <div class="game">

    <div class="game-div">
      <div class="game-min">
        <div v-for="(e,i) in frame" :key="i" class="row">
          <p v-for="(b,j) in e" :key="j" class="element" :style="{background:b.bg}">
          </p>
        </div>
      </div>
      <div class="right-div">
        <div>
          <p>得分</p>
          <p>{{ score }}</p>
        </div>
        <div>
          <p>等级</p>
          <el-input-number v-model="lever" @change="leverChange"></el-input-number>
        </div>
        <div>
          <p>吃</p>
          <p>{{ times }}</p>
        </div>
        <div @click="autMove(true)" class="ztks">
          暂停/开始
        </div>
        <div @click="Reset" class="ztks">
          重新开始
        </div>
      </div>
    </div>
    <div class="control">
      <p @click="moveTop">向上</p>
      <div class="lr">
        <p @click="moveLeft">向左</p>
        <p @click="moveRight">向右</p>
      </div>
      <p @click="moveTottom">向下</p>
    </div>
  </div>
</template>

<script setup>
import {onMounted, ref, onUnmounted} from "vue";

const row = ref(20);
const col = ref(20);
const frame = ref([]);
const bg = ref("#eee");
const snake = ref({});
import {color} from "@/utils/ykdata.js";

const colors = ref(color[0])

const headColor = ref('#2B9DF5')

const wall = ref([])

const food = ref({})

const over = ref(false)

const timer = ref('')

const speed = ref(600)
const fx = ref(0)

const tail = ref([])

const times = ref(0)

const lever = ref(1)

const score = ref(0)

const site = ref(0)

const changeDirection = ref(5)


//游戏框架
const gameFrame = () => {
  for (let i = 0; i < row.value; i++) {
    let a = [];
    for (let j = 0; j < col.value; j++) {
      let b = {
        bg: bg.value,
      };
      a.push(b);
    }
    frame.value.push(a);
  }
}
const Reset = () => {
  clearInterval(timer.value)
  over.value = false
  renderBlock(snake.value, frame.value, 0)
  initSnake()
  moveLeft(true)
}
//初始化蛇
const initSnake = () => {
  snake.value = {
    // site: [9, 8, 9, 9, 9, 10],
    site: [9, 8, 9, 9, 9, 10,9,11,9,12],
    color: colors.value[6]
  }
  renderBlock(snake.value, frame.value, 1)
}
//方块渲染
//a:方块,b:渲染位置,n类型: 0为清除,1为生成
const renderBlock = (a, b, n) => {
  let c = a.site
  if (n == 1) {
    for (let i = 0; i < a.site.length; i += 2) {
      b[c[i]][c[i + 1]].bg = a.color
    }
    b[c[0]][c[1]].bg = headColor.value
  } else if (n == 0) {
    for (let i = 0; i < a.site.length; i += 2) {
      b[c[i]][c[i + 1]].bg = bg.value
    }
  }
}

const renderBlockFood = (a, b, n) => {
  let c = a.site
  if (n == 1) {
    for (let i = 0; i < a.site.length; i += 2) {
      b[c[i]][c[i + 1]].bg = a.color
    }
  } else if (n == 0) {
    for (let i = 0; i < a.site.length; i += 2) {
      b[c[i]][c[i + 1]].bg = bg.value
    }
  }
}

const move = () => {
  if (hasConsecutiveEqualSubarray()) {
    tail.value = removeLastTwoAndReturn()
  }

  for (let i = snake.value.site.length - 1; i > 1; i -= 2) {
    snake.value.site[i] = snake.value.site[i - 2]
    snake.value.site[i - 1] = snake.value.site[i - 3];
  }
}

const hasConsecutiveEqualSubarray = () => {
  for (let i = snake.value.site.length - 1; i > 1; i -= 2) {
    if (snake.value.site[i] == snake.value.site[i - 2] && snake.value.site[i - 1] == snake.value.site[i - 3]) {
      return true;
    }
  }
  return false;
}

const removeLastTwoAndReturn = () => {
  if (snake.value.site.length < 2) {
    throw new Error("数组长度不足，无法移除两个元素");
  }
  // 移除最后一个元素
  let lastElement = snake.value.site.pop();
  // 再次移除最后一个元素
  let secondLastElement = snake.value.site.pop();
  // 返回移除的两个元素
  return [secondLastElement, lastElement];
}

const initFood = () => {
  foods()
  let color = colors.value[Math.floor(Math.random() * 7)]
  food.value = {site, color}
  renderBlockFood(food.value, frame.value, 1)
}

const foods = () => {
  site.value = [Math.floor(Math.random() * row.value), Math.floor(Math.random() * col.value)];
  // site.value = [9, 3];
  for (let i = 0; i < snake.value.site.length; i += 2) {
    if (snake.value.site[i] == site.value[0] && snake.value.site[i + 1] == site.value[1]) {
      foods()
    }
  }
}


const moveLeft = async (initiate) => {

  if ((!over.value && fx.value != 1 && changeDirection.value != 0) || initiate) {
    clearInterval(timer.value)
    fx.value = 0
    changeDirection.value = 0
    leftSmall()
    timer.value = setInterval(() => {
      if (!over.value||initiate){
        leftSmall()
      }else{
        clearInterval(timer.value)
      }
    }, speed.value)

  }
}


const leftSmall = () => {
  renderBlock(snake.value, frame.value, 0)
  move()
  snake.value.site[1]--
  if (tail.value.length > 0) {
    snake.value.site.push(tail.value[0])
    snake.value.site.push(tail.value[1])
  }
  tail.value = []
  // eat(snake.value.site[0], snake.value.site[1] - 1)
  eat(snake.value.site[0], snake.value.site[1])
  if (snake.value.site[1] < 0) {
    snake.value.site[1] = 19
  }
  oneself()
  renderBlock(snake.value, frame.value, 1)
}

const moveRight = async (initiate) => {

  if ((!over.value && fx.value != 0 && changeDirection.value != 1) || initiate) {
    clearInterval(timer.value)
    rightSmall()
    timer.value = setInterval(() => {
      if (!over.value||initiate){
        rightSmall()
      }else{
        clearInterval(timer.value)
      }
    }, speed.value)

  }
}
const rightSmall = () => {
  fx.value = 1
  changeDirection.value = 1
  renderBlock(snake.value, frame.value, 0)
  move()
  snake.value.site[1]++
  if (tail.value.length > 0) {
    snake.value.site.push(tail.value[0])
    snake.value.site.push(tail.value[1])
  }
  // eat(snake.value.site[0], snake.value.site[1] + 1)
  eat(snake.value.site[0], snake.value.site[1])
  tail.value = []
  if (snake.value.site[1] >= col.value) {
    snake.value.site[1] = 0
  }
  oneself()
  renderBlock(snake.value, frame.value, 1)
}


const moveTop = async (initiate) => {
  if ((!over.value && fx.value != 3 && changeDirection.value != 2) || initiate) {
    fx.value = 2
    changeDirection.value = 2
    clearInterval(timer.value)
    topSmall()
    timer.value = setInterval(() => {

      if (!over.value||initiate){
        topSmall()
      }else{
        clearInterval(timer.value)
      }
    }, speed.value)

  }
}
const topSmall = () => {
  renderBlock(snake.value, frame.value, 0)

  move()
  snake.value.site[0]--
  if (tail.value.length > 0) {
    snake.value.site.push(tail.value[0])
    snake.value.site.push(tail.value[1])
  }
  tail.value = []
  // eat(snake.value.site[0] - 1, snake.value.site[1])
  eat(snake.value.site[0], snake.value.site[1])
  if (snake.value.site[0] < 0) {
    snake.value.site[0] = 19
  }
  oneself()
  renderBlock(snake.value, frame.value, 1)
}


const moveTottom = async (initiate) => {

  if ((!over.value && fx.value != 2 && changeDirection.value != 3) || initiate) {
    fx.value = 3
    changeDirection.value = 3
    clearInterval(timer.value)
    tottomSmall()
    timer.value = setInterval(() => {
      if (!over.value||initiate){
        tottomSmall()
      }else{
        clearInterval(timer.value)
      }
    }, speed.value)

  }
}

const tottomSmall = () => {
  fx.value = 3
  renderBlock(snake.value, frame.value, 0)

  move()
  snake.value.site[0]++
  if (tail.value.length > 0) {
    snake.value.site.push(tail.value[0])
    snake.value.site.push(tail.value[1])
  }
  tail.value = []
  // eat(snake.value.site[0], snake.value.site[1])
  eat(snake.value.site[0], snake.value.site[1])
  if (snake.value.site[0] >= row.value) {
    snake.value.site[0] = 0
  }
  oneself()
  renderBlock(snake.value, frame.value, 1)
}

const moveAll = async (direction) => {
  if (direction === 'left') {
    await moveLeft()
  } else if (direction === 'right') {
    await moveRight()
  } else if (direction === 'top') {
    await moveTop()
  } else if (direction === 'tottom') {
    await moveTottom()
  }
}

const autMove = (initiate) => {
  if (timer.value) {
    clearInterval(timer.value)
    timer.value = ''
  } else {
    if (fx.value == 0) {
      moveLeft(initiate)
    } else if (fx.value == 1) {
      moveRight(initiate)
    } else if (fx.value == 2) {
      moveTop(initiate)
    } else if (fx.value == 3) {
      moveTottom(initiate)
    }
  }
}

const oneself = () => {
  let t = [snake.value.site[0], snake.value.site[1]]
  for (let i = snake.value.site.length - 1; i > 1; i -= 2) {
    // debugger
    if (snake.value.site[i] == t[1] && snake.value.site[i - 1] == t[0]) {
      alert('over')
      over.value = true
    }
  }
}

const eat = (i, j) => {
  if (i == food.value.site[0] && j == food.value.site[1]) {
    let head = snake.value.site[snake.value.site.length - 2]
    let theTail = snake.value.site[snake.value.site.length - 1]
    snake.value.site.push(head)
    snake.value.site.push(theTail)
    initFood()
    times.value++
    let lev = Math.floor(times.value / 10) + 1
    if (lev > lever.value) {
      {
        lever.value = lev
        //速递
        if (lever.value < 15) {
          speed.value = 600 - (lever.value - 1) * 40
        } else {
          speed.value = 30
        }
        clearInterval(timer.value)
        autMove()
      }
    }


    score.value = score.value + lever.value * 100
  }
}

const leverChange = () => {
  speed.value = 600 - (lever.value - 1) * 40
  clearInterval(timer.value)
  autMove()
}

const handleKeydown = async (event) => {
  const {key, keyCode} = event;
  // 检查按下的是否为方向键
  switch (key) {
    case 'ArrowUp':
      await moveTop()
      break;
    case 'ArrowDown':
      // 处理 ArrowDown 逻辑
      await moveTottom()
      break;
    case 'ArrowLeft':
      // 处理 ArrowLeft 逻辑
      await moveLeft()
      break;
    case 'ArrowRight':
      // 处理 ArrowRight 逻辑
      await moveRight()
      break;
    case 'w':
      await moveTop()
      break;
    case 's':
      // 处理 ArrowDown 逻辑
      await moveTottom()
      break;
    case 'a':
      // 处理 ArrowLeft 逻辑
      await moveLeft()
      break;
    case 'd':
      // 处理 ArrowRight 逻辑
      await moveRight()
      break;
    default:
      // 处理其他按键逻辑
      break;
  }
};

onMounted(() => {
  gameFrame()
  initSnake()
  initFood()
  autMove()
  window.addEventListener('keydown', handleKeydown)
})

onUnmounted(() => {
  // 移除键盘事件监听
  window.removeEventListener('keydown', handleKeydown);
});


</script>

<style scoped lang="less">

.game {
  .game-div {
    display: flex;

    .game-min {
      .row {
        display: flex;
        padding-bottom: 1px;

        .element {
          height: 12px;
          width: 12px;
          margin-left: 1px;
          margin-right: 1px;
        }
      }
    }

    .right-div {
      padding-left: 12px;

      .ztks {
        margin-top: 20px;
        line-height: 40px;
        padding: 0 8px;
        background: #eee;
        cursor: pointer;
      }
    }
  }
}

.control {
  width: 240px;
  padding-top: 20px;

  p {
    margin: 10px;
    padding: 8px;
    background: #eee;
    cursor: pointer;
    text-align: center;
    min-width: 90px;
  }

  .lr {
    display: flex;
    width: 100%;
    justify-content: space-between;
  }
}

//.a{
//  background-color: #FFA7EB;
//  background-color: #DFA1FF;
//  background-color: #7BE7FF;
//  background-color: #9EAAFF;
//  background-color: #89FED8;
//  background-color: #FFED48;
//  background-color: #FFBA8D;
//}
</style>


